﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prisa.Entities;
using Prisa.DataAccess;
using Microsoft.Practices.Unity;

namespace Prisa.BussinesLogic
{
    public class CreditoBL:ICreditoBL
    {
        [Dependency]
        public ICreditoDAO creditoDAO { get; set; }

        [Dependency]
        public IDetalleCreditoDAO detalleCreditoDAO { get; set; }

        [Dependency]
        public IProductoDAO productoDAO { get; set; }

        [Dependency]
        public IHistorialVentaDAO historialDAO { get; set; }

        [Dependency]
        public ICategoriaDAO categoriaDAO { get; set; }

        public List<CREDITO> GetAllFromCreditos()
        {
            return creditoDAO.GetAllFromCreditos();
        }

        public List<CREDITO> GetFromCreditobyCliente(string cliente)
        {
            return creditoDAO.GetFromCreditobyCliente(cliente);
        }

        public List<CREDITO> GetFromCreditobyFechaAndCliente(DateTime? fec1, DateTime? fec2, string cliente)
        {
            return creditoDAO.GetFromCreditobyFechaAndCliente(fec1, fec2, cliente);
        }

        public CREDITO GetFromCreditoById(int id)
        {
            return creditoDAO.GetFromCreditoById(id);
        }

        public void AddCredito(CREDITO credito)
        {
            var msg = "";
            var ok = credito.Validate(out msg);
            if (ok)
            {
                ValidarStocks(credito);
                creditoDAO.AddCredito(credito);

                #region UpdateStock
                foreach (var item in credito.DETALLE_CREDITO)
                {
                    //var producto = productoDAO.GetFromProductoById(item.PRODUCTO.Id);
                    //var categoria = categoriaDAO.GetFromCategoriaById(item.PRODUCTO.CategoriaId);

                    var producto = productoDAO.GetFromProductoById(item.ProductoId);
                    var categoria = categoriaDAO.GetFromCategoriaById(producto.CategoriaId);
                    #region AddHistorial
                    var historial_ventas = new HISTORIAL_VENTAS
                    {
                        ProductoId = item.ProductoId,    Fecha = DateTime.Today.Date,
                        Precio = producto.Precio,    Cantidad = Convert.ToInt32(item.Cantidad),
                        Total = producto.Precio * item.Cantidad,
                        Credito = true,   Menudeo = false,   Contado = false,
                        Cancelada = false,   Observacion = " ",
                    };
                    historialDAO.AddHistorialVentas(historial_ventas);
                    #endregion

                    //actualizar stock venta
                    var actproducto = producto;
                    actproducto.CATEGORIA = categoria;
                    actproducto.Stock = producto.Stock - item.Cantidad;
                    productoDAO.UpdateProducto(actproducto);
                }
                #endregion
                
            }
            else
            {
                throw new Exception(msg);
            }

        }

        public void UpdateCredito(CREDITO credito)
        {
            var msg = "";
            var ok = credito.Validate(out msg);
            if (ok)
            {
                ValidarStockEditar(credito);

                #region UpdateProductos
                foreach (var item in credito.DETALLE_CREDITO)
                {
                    if (item.id == 0)
                    {
                        var prod = productoDAO.GetFromProductoById(item.PRODUCTO.Id);
                        var historial_ventas = new HISTORIAL_VENTAS
                        {
                            ProductoId = item.ProductoId,
                            Fecha = DateTime.Today.Date,Precio = prod.Precio,
                            Cantidad = Convert.ToInt32(item.Cantidad),
                            Total = prod.Precio * item.Cantidad,
                            Credito = true,Contado = false,Menudeo = false,
                            Cancelada = false,Observacion = " ",
                        };
                        historialDAO.AddHistorialVentas(historial_ventas);
                    }
                    else
                    {
                        var detalle = detalleCreditoDAO.GetDetalleCreditoByCreditoIdAndProductoId(item.id, credito.Id, item.ProductoId);
                        var cantidadAct = Convert.ToInt32(detalle.Cantidad);

                        var nuevaCant = Convert.ToInt32(item.Cantidad);

                        historialDAO.UpdateHistorialCredito(item.PRODUCTO.Id, credito.FechaCredito, item.PRODUCTO.Precio, cantidadAct, nuevaCant);
                    }

                    //actualizar stock productos
                    var existeDetal = detalleCreditoDAO.GetDetalleCreditoByCreditoIdAndProductoId(item.id, credito.Id, item.ProductoId);
                    if (existeDetal != null)
                    {
                        if (item.Cantidad != existeDetal.Cantidad)
                        {
                            var producto = productoDAO.GetFromProductoById(item.ProductoId);
                            var categoria = categoriaDAO.GetFromCategoriaById(producto.CategoriaId);

                            var productoAlm = producto;
                            productoAlm.CATEGORIA = categoria;
                            productoAlm.Stock = producto.Stock + existeDetal.Cantidad - item.Cantidad;
                            productoDAO.UpdateProducto(productoAlm);
                        }
                    }
                    else
                    {
                        var producto = productoDAO.GetFromProductoById(item.ProductoId);
                        var categoria = categoriaDAO.GetFromCategoriaById(producto.CategoriaId);

                        var actproducto = producto;
                        actproducto.CATEGORIA = categoria;
                        actproducto.Stock = producto.Stock - item.Cantidad;
                        productoDAO.UpdateProducto(actproducto);
                    }
                }
                #endregion 

                creditoDAO.UpdateCredito(credito);
                
            }
            else
            {
                throw new Exception(msg);
            }
        }

        private void ValidarStocks(CREDITO credito)
        {
            foreach (var item in credito.DETALLE_CREDITO)
            {
                var producto = productoDAO.GetFromProductoById(item.PRODUCTO.Id);
                var cantActualDetalle = detalleCreditoDAO.GetDetalleCreditoByCreditoIdAndProductoId(item.id, credito.Id, item.ProductoId);

                if (cantActualDetalle == null)
                {
                    if (item.Cantidad > producto.Stock)
                    {
                        throw new Exception(string.Format("No hay Stock suficiente para el producto {0}," +
                                          " solo quedan {1} Und.", producto.Descripcion, producto.Stock));
                    }
                }
                if (cantActualDetalle != null)
                {
                    var stockActual = producto.Stock + cantActualDetalle.Cantidad;
                    if (item.Cantidad > stockActual)
                    {
                        throw new Exception(string.Format("La maxima cantidad a elegir del producto {0}," +
                                          " es {1} Und.", producto.Descripcion, stockActual));
                    }
                }
            }
        }

        private void ValidarStockEditar(CREDITO credito)
        {
            foreach (var item in credito.DETALLE_CREDITO)
            {
                var producto = productoDAO.GetFromProductoById(item.PRODUCTO.Id);
                var cantActualDetalle = detalleCreditoDAO.GetDetalleCreditoByCreditoIdAndProductoId(item.id, credito.Id, item.ProductoId);

                if (cantActualDetalle == null)
                {
                    if (item.Cantidad > producto.Stock)
                    {
                        throw new Exception(string.Format("No hay Stock suficiente para el producto {0}," +
                                          " solo quedan {1} Und.", producto.Descripcion, producto.Stock));
                    }
                }
                if (cantActualDetalle != null)
                {
                    var stockActual = producto.Stock + cantActualDetalle.Cantidad;
                    if (item.Cantidad > stockActual)
                    {
                        throw new Exception(string.Format("La maxima cantidad a elegir del producto {0}," +
                                          " es {1} Und.", producto.Descripcion, stockActual));
                    }
                }
            }
        }

        public List<CREDITO> GetAllFromCreditosSoloDeuda()
        {
            return creditoDAO.GetAllFromCreditosSoloDeuda();
        }
    }
}
